﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.UI.WebControls;
using Intellego.Web.ValidationEngine;
using MIAP.Entidades;
using MIAP.Negocio;
using MIAPWEB.Common;

namespace MIAPWEB.Forms
{
    public partial class AltaPerfil : PageBase
    {
        #region Variables
        /// <summary>
        /// Clase de negocio para perfiles
        /// </summary>
        private readonly AltaPerfilesNegocio altaPerfilesNegocio;

        /// <summary>
        /// Clase de negocio para proyectos
        /// </summary>
        private readonly AdministrarProyectosNegocio administrarProyectosNegocio;

        /// <summary>
        /// Clase de negocio para las operaciones comunes del sistema.
        /// </summary>
        private ComunesNegocio comunesNegocio;

        #endregion

        #region Constantes
        #endregion

        #region Propiedades

        /// <summary>
        /// Id del perfil 
        /// </summary>
        private int? IdPerfil
        {
            get
            {
                if (this.ViewState[AppQueryStrings.IdPerfil] == null)
                {
                    this.ViewState[AppQueryStrings.IdPerfil] = this.Request.QueryString[AppQueryStrings.IdPerfil];
                }

                return Convert.ToInt32(this.ViewState[AppQueryStrings.IdPerfil]);
            }

            set
            {
                this.ViewState[AppQueryStrings.IdPerfil] = value;
            }
        }

        /// <summary>
        /// Bandera que habilita o inhabilita la validación del campo proyecto
        /// </summary>
        private bool DisableProjectValidation
        {

            get
            {
                if (ViewState["DisableProjectValidation"] == null)
                    ViewState["DisableProjectValidation"] = false;
                return (bool)ViewState["DisableProjectValidation"];
            }

            set
            {
                this.ViewState["DisableProjectValidation"] = value;
            }
        }

        /// <summary>
        /// Lista de funciones
        /// </summary>
        private List<PerfilUrlInfo> ListaFunciones
        {
            get
            {
                if (this.ViewState["ListaFunciones"] == null)
                {
                    this.ViewState["ListaFunciones"] = new List<PerfilUrlInfo>();
                }
                return this.ViewState["ListaFunciones"] as List<PerfilUrlInfo>;
            }

            set
            {
                this.ViewState["ListaFunciones"] = value;
            }
        }

        /// <summary>
        /// Lista de funciones seleccionadas
        /// </summary>
        private List<PermisoInfo> ListaFuncionesSeleccionadas
        {
            get
            {
                if (this.ViewState["ListaFuncionesSeleccionadas"] == null)
                {
                    this.ViewState["ListaFuncionesSeleccionadas"] = new List<PermisoInfo>();
                }
                return this.ViewState["ListaFuncionesSeleccionadas"] as List<PermisoInfo>;
            }

            set
            {
                this.ViewState["ListaFuncionesSeleccionadas"] = value;
            }
        }

        /// <summary>
        /// Indica la cantidad de registros por página del grid
        /// </summary>
        private int GridViewPageSize
        {
            get { return Convert.ToInt32(new ConfiguracionNegocio().GetNumeroPaginasGrid().Descripcion); }
        }

        #endregion

        #region Eventos

        /// <summary>
        /// Evento que se ejecuta al cargar la página.
        /// </summary>
        /// <param name="sender">Objeto que invoca el evento.</param>
        /// <param name="e">Argumentos del evento.</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                if (Request.UrlReferrer != null) this.PreviousPage = Request.UrlReferrer.ToString();
                this.grdFunciones.PageSize = this.GridViewPageSize;                
                this.LoadinitialCatalogs();
                this.lblTitulo.Text = this.GetGlobalResourceObject("Strings", "lblTituloAltaPerfiles").ToString();
               // this.AppendDefaultDropDownItem();
                if (this.IdPerfil != null && this.IdPerfil>0)
                {
                    this.LoadPerfil((int)this.IdPerfil);
                    this.lblTitulo.Text = this.GetGlobalResourceObject("Strings", "lblTituloEdicionPerfiles").ToString();
                }                
            }
            this.InitValidation();
        }

        /// <summary>
        /// Evento que se ejecuta al cambiar de página en el grid
        /// </summary>
        /// <param name="sender">Objeto que invoca el evento.</param>
        /// <param name="e">Argumentos del evento.</param>
        protected void grdFunciones_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            List<PermisoInfo> listaPermisosSeleccionados = GetPermisos();
            grdFunciones.PageIndex = e.NewPageIndex;
            grdFunciones.DataSource = this.ListaFunciones;
            grdFunciones.DataBind();
            SetPermisos(this.ListaFuncionesSeleccionadas);
        }

        /// <summary>
        /// Evento del click en el boton de guardar
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void BtnGuardar_Click(object sender, EventArgs e)
        {           
            // Valida que no exista un perfil con el mismo nombre.
            if (this.IdPerfil == default(int) || this.IdPerfil == null)
            {
                string nombrePerfil = this.txtNombre.Text.Trim().ToLower();

                nombrePerfil = Regex.Replace(nombrePerfil, @"\s+", " ");

                // Verifica la existencia del proyecto.
                if (this.VerifyExistPerfil(nombrePerfil))
                {
                    this.ShowMessage(this.GetGlobalResourceObject("Strings", "AltaPerfil_PerfilExistente").ToString());
                }
                else
                {
                    this.Save();
                }
            }
            else
            {
                this.Save();
            }
        }

        /// <summary>
        /// Evento del click en el boton de salir o regresar.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void BtnSalir_Click(object sender, EventArgs e)
        {
            Response.Redirect(this.PreviousPage);
        }

        #endregion

        #region Métodos

        /// <summary>
        /// Establece las validaciones de la página.
        /// </summary>
        private void InitValidation()
        {
            //Asocia las reglas de validación a sus respectivos controles
            ValidationRule ruleProyecto = new ValidationRule(this.ddlProyecto);
            ValidationRule ruleNombre = new ValidationRule(this.txtNombre);
            ValidationRule ruleActivo = new ValidationRule(this.ddlEstatus);

            //Establece las reglas de validación
            ruleProyecto.NotEmpty(this.GetGlobalResourceObject("strings", "ErrorDropDownRequerido").ToString());
            ruleNombre.NotEmpty(this.GetGlobalResourceObject("strings", "ErrorRequerido").ToString());
            ruleActivo.NotEmpty(this.GetGlobalResourceObject("strings", "ErrorDropDownRequerido").ToString());

            //Establece validación en línea
            ruleActivo.InLineValidation = true;
            ruleNombre.InLineValidation = true;
            ruleProyecto.InLineValidation = true;

            //Agrega las validaciones a ejecutarse
            if (!this.DisableProjectValidation)
                this.ValidationEngine.Add(ruleProyecto);
            this.ValidationEngine.Add(ruleNombre);
            this.ValidationEngine.Add(ruleActivo);
            //Agrega la validación de funciones
            InitGridViewValidation();

            //Agrega la opción para respetar la longitud máxima en las cajas de texto multilínea
            this.ValidationEngine.FixTextBoxMultiLine = true;
        }

        /// <summary>
        /// Agrega la regla de validación de las funciones
        /// </summary>
        private void InitGridViewValidation()
        {
            List<CheckBox> listaCasillas = new List<CheckBox>();
            foreach (GridViewRow row in grdFunciones.Rows)
            {
                CheckBox chkSeleccionar = row.FindControl("chkSeleccionar") as CheckBox;
                if (row.RowIndex == (grdFunciones.Rows.Count -1))
                {
                    ValidationRule ruleFuncion = new ValidationRule(chkSeleccionar);
                    ruleFuncion.MinCheckBox(1, listaCasillas, this.GetGlobalResourceObject("strings", "ErrorSeleccionarElemento").ToString());
                    ruleFuncion.InLineValidation = true;
                    this.ValidationEngine.Add(ruleFuncion);
                }
                else
                    listaCasillas.Add(chkSeleccionar);
            }
      
        }

        /// <summary>
        /// Constructor inicial
        /// </summary>
        public AltaPerfil()
        {
            this.altaPerfilesNegocio = new AltaPerfilesNegocio();
            this.administrarProyectosNegocio = new AdministrarProyectosNegocio();
            this.comunesNegocio = new ComunesNegocio();
        }

        /// <summary>
        /// Guarda la información del perfil
        /// </summary>
        private void Save()
        {
            var lista = GetPermisos();

            int? idProyecto = Convert.ToInt32(ddlProyecto.SelectedValue) > 0 ? Convert.ToInt32(ddlProyecto.SelectedValue) : (int?)null ;
            var loPerfil = new PerfilInfo
                {
                    IdPerfil = this.IdPerfil ?? 0,
                    NombrePerfil = this.txtNombre.Text,
                    Descripcion = this.txtDescripcion.Text,
                    Proyecto =  idProyecto.HasValue ?  new ProyectoInfo { IDProyecto = idProyecto.Value }: null,
                    EstaActivo = Convert.ToBoolean(Convert.ToInt32(ddlEstatus.SelectedValue)),
                    Permisos = this.ListaFuncionesSeleccionadas
                };
            this.Clean();
            var mensajeGuardado = this.GetGlobalResourceObject("strings", "GuardadoExitoso").ToString();
            if (this.IdPerfil == null || this.IdPerfil == 0)
            {
                this.altaPerfilesNegocio.AddNewPerfil(loPerfil, AppSessionManager.Instance.Usuario);
                this.ShowMessage(mensajeGuardado);
                AppSessionManager.Instance.RecalculaPermisos();
            }
            else
            {
                this.altaPerfilesNegocio.EditPerfil(loPerfil, AppSessionManager.Instance.Usuario);
                AppSessionManager.Instance.RecalculaPermisos();
                this.ShowMessage(mensajeGuardado, this.PreviousPage);
            }
        }

        /// <summary>
        /// Obtiene los permisos asociados al perfil
        /// </summary>
        /// <returns>List<PermisoInfo></returns>
        private List<PermisoInfo> GetPermisos()
        {
            List<PermisoInfo> lista = new List<PermisoInfo>();
            foreach (GridViewRow renglon in grdFunciones.Rows)
            {
                var chkSeleccionar = renglon.FindControl("chkSeleccionar") as CheckBox;
                int idPerfilUrl = Convert.ToInt32(grdFunciones.DataKeys[renglon.RowIndex].Value);
                if (!chkSeleccionar.Checked)
                {
                    if (this.ListaFuncionesSeleccionadas.Any(f=> f.Identificador == idPerfilUrl))
                    {
                        ListaFuncionesSeleccionadas.Remove(this.ListaFuncionesSeleccionadas.Where(f => f.Identificador == idPerfilUrl).First());
                    }
                    continue;
                }
                PermisoInfo permiso = new PermisoInfo
                {
                    Identificador = idPerfilUrl,
                    PerfilUrl = new PerfilUrlInfo { IdPerfilUrl = idPerfilUrl }
                };

                lista.Add(permiso);
                
                if (!this.ListaFuncionesSeleccionadas.Any(f => f.Identificador == idPerfilUrl))
                {
                    ListaFuncionesSeleccionadas.Add(permiso);
                }

            }
            return lista;
        }

        /// <summary>
        /// Selecciona las funciones a las que se tiene permiso en el grid de funciones
        /// </summary>
        /// <param name="permisos"></param>
        private void SetPermisos(List<PermisoInfo> permisos)
        {
            List<PermisoInfo> lista = new List<PermisoInfo>();
            foreach (GridViewRow renglon in grdFunciones.Rows)
            {
                int idPerfilUrl = Convert.ToInt32(grdFunciones.DataKeys[renglon.RowIndex].Value);
                bool tienePermiso = permisos.Any(p => p.Identificador == idPerfilUrl);
                var chkSeleccionar = renglon.FindControl("chkSeleccionar") as CheckBox;
                chkSeleccionar.Checked = tienePermiso;
            }
        }

        /// <summary>
        /// Carga la informacion del perfil 
        /// </summary>
        /// <param name="idPerfil">Id del perfil a editar</param>
        private void LoadPerfil(int idPerfil)
        {
            var perfil = this.altaPerfilesNegocio.GetPerfilById(idPerfil);
            this.txtDescripcion.Text = perfil.Descripcion;
            this.txtNombre.Text = perfil.NombrePerfil;
            this.ddlEstatus.SelectedValue = Convert.ToInt32(perfil.Estatus.ToString().ToUpper() == "ACTIVO").ToString(CultureInfo.InvariantCulture);
            this.ddlProyecto.SelectedValue = perfil.Proyecto.IDProyecto.ToString(CultureInfo.InvariantCulture);
            List<PermisoInfo> listaPermisos = this.altaPerfilesNegocio.GetPermisosByIdPerfil(perfil.IdPerfil);
            this.ListaFuncionesSeleccionadas = listaPermisos;
            SetPermisos(listaPermisos);
            if (perfil.Proyecto == null || perfil.Proyecto.IDProyecto == 0)
                DisableProjectValidation = true;
            this.ddlProyecto.Enabled = !DisableProjectValidation;
        }

        /// <summary>
        /// Limpia los controles de la pagina
        /// </summary>
        private void Clean()
        {
            this.txtDescripcion.Text = string.Empty;
            this.txtNombre.Text = string.Empty;
            this.ddlEstatus.SelectedIndex = -1;
            this.ddlProyecto.SelectedIndex = -1;
            this.ListaFuncionesSeleccionadas = new List<PermisoInfo>();
            SetPermisos(this.ListaFuncionesSeleccionadas);
        }

        /// <summary>
        /// Agrega al inicio del drop down el item seleccionar
        /// </summary>
        private void AppendDefaultDropDownItem()
        {
            var mensajeSeleccioanr = this.GetGlobalResourceObject("strings", "Seleccionar").ToString();
            this.comunesNegocio.SetSeleccionar(mensajeSeleccioanr, this.ddlProyecto);
            this.comunesNegocio.SetSeleccionar(mensajeSeleccioanr, this.ddlEstatus);
        }

        /// <summary>
        /// llena los dropdowns de la pagina
        /// </summary>
        private void LoadinitialCatalogs()
        {
            this.GetProyectos();
            this.GetEstatusPerfil();
            this.GetFunciones();
        }

        /// <summary>
        /// Obtiene los proyectos.
        /// </summary>
        public void GetProyectos()
        {
            this.ddlProyecto.DataSource = AppSessionManager.Instance.GetProyectosByPagina(AppUrls.AdministrarArchivos);
            this.ddlProyecto.DataBind();
        }

        /// <summary>
        /// Obtiene los estatus del perfil.
        /// </summary>
        public void GetEstatusPerfil()
        {
            this.ddlEstatus.DataSource = this.comunesNegocio.GetEstatus();
            this.ddlEstatus.DataBind();
        }

        /// <summary>
        /// Obtiene el catálogo de funciones
        /// </summary>
        public void GetFunciones()
        {
            this.ListaFunciones = this.altaPerfilesNegocio.GetPerfilUrl();
            this.grdFunciones.DataSource = this.ListaFunciones;
            this.grdFunciones.DataBind();
        }

        /// <summary>
        /// Verifica la existencia de un perfil.
        /// </summary>
        /// <param name="nombrePerfil">Es el nombre del perfil.</param>
        /// <returns>Indicador de si el perfil existe o no.</returns>
        public bool VerifyExistPerfil(string nombrePerfil)
        {
            return this.altaPerfilesNegocio.VerifyExistPerfil(nombrePerfil);
        }

        #endregion        
    }
}